home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / hlvis / vis.cpp < prev    next >
C/C++ Source or Header  |  2002-12-08  |  49KB  |  1,784 lines

  1. /*
  2.  
  3.     VISIBLE INFORMATION SET    -aka-    V I S
  4.  
  5.     Code based on original code from Valve Software, 
  6.     Modified by Sean "Zoner" Cavanaugh (seanc@gearboxsoftware.com) with permission.
  7.     Modified by Tony "Merl" Moore (merlinis@bigpond.net.au)
  8.     Contains code by Skyler "Zipster" York (zipster89134@hotmail.com) - Included with permission.
  9.     
  10. */
  11.  
  12. #include "vis.h"
  13.  
  14. #ifdef ZHLT_NETVIS
  15. #include "zlib.h"
  16. #endif
  17.  
  18. /*
  19.  
  20.  NOTES
  21.  
  22. */
  23.  
  24. int             g_numportals = 0;
  25. unsigned        g_portalleafs = 0;
  26.  
  27. portal_t*       g_portals;
  28.  
  29. leaf_t*         g_leafs;
  30.  
  31. // AJM: MVD
  32. #ifdef HLVIS_MAXDIST
  33. byte*            g_mightsee;
  34. visblocker_t    g_visblockers[MAX_VISBLOCKERS];
  35. int                g_numvisblockers = 0;
  36. #endif
  37. //
  38.  
  39. static byte*    vismap;
  40. static byte*    vismap_p;
  41. static byte*    vismap_end;                                // past visfile
  42. static int      originalvismapsize;
  43.  
  44. byte*           g_uncompressed;                            // [bitbytes*portalleafs]
  45.  
  46. unsigned        g_bitbytes;                                // (portalleafs+63)>>3
  47. unsigned        g_bitlongs;
  48.  
  49. bool            g_fastvis = DEFAULT_FASTVIS;
  50. bool            g_fullvis = DEFAULT_FULLVIS;
  51. bool            g_estimate = DEFAULT_ESTIMATE;
  52. bool            g_chart = DEFAULT_CHART;
  53. bool            g_info = DEFAULT_INFO;
  54.  
  55. #ifdef HLVIS_MAXDIST
  56. // AJM: MVD
  57. unsigned int    g_maxdistance = DEFAULT_MAXDISTANCE_RANGE;
  58. //bool            g_postcompile = DEFAULT_POST_COMPILE;
  59. //
  60. #endif
  61.  
  62. #ifdef ZHLT_PROGRESSFILE // AJM
  63. char*           g_progressfile = DEFAULT_PROGRESSFILE; // "-progressfile path"
  64. #endif
  65.  
  66. static int      totalvis = 0;
  67.  
  68. #if ZHLT_ZONES
  69. Zones*          g_Zones;
  70. #endif
  71.  
  72. #ifdef ZHLT_NETVIS
  73. // -- these are definitions and initializations of C/CPP common variables
  74. volatile int    g_visportalindex = UNINITIALIZED_PORTAL_INDEX;  // a client's portal index : current portalindex being worked on
  75.  
  76.  
  77. volatile int    g_visportals = 0;                          // the total portals in the map
  78. volatile int    g_visleafs = 0;                            // the total portal leafs in the map
  79. volatile int    g_vislocalportal = 0;                      // number of portals solved locally
  80. volatile enum vis_states g_visstate = VIS_STARTUP;         // current step of execution
  81. volatile enum vis_modes g_vismode = VIS_MODE_NULL;         // style of execution (client or server)
  82. volatile int    g_visleafthread = 0;                       // control flag (are we ready to leafthread)
  83. unsigned int    g_rate = DEFAULT_NETVIS_RATE;
  84. volatile double g_starttime = 0;                           // Start time (from I_FloatTime())
  85. volatile unsigned long g_idletime = 0;                     // Accumulated idle time in milliseconds (rolls over after 46.7 days, hopefully a vis client wont run that long)
  86. volatile unsigned long g_serverindex = 0;                  // client only variable, server index for calculating percentage indicators on the client
  87. short           g_port = DEFAULT_NETVIS_PORT;
  88. const char*     g_server_addr = NULL;
  89.  
  90.  
  91. volatile bool   g_bsp_downloaded = false;       // Client variable
  92. volatile bool   g_prt_downloaded = false;       // Client variable
  93. volatile bool   g_mightsee_downloaded = false;  // Client variable
  94.  
  95. char*           g_bsp_image = NULL;         // Client/Server variable : Server uses it for cache for connecting clients, clients download it to memory to not require filesystem usage 
  96. char*           g_prt_image = NULL;         // Client/Server variable : Server uses it for cache for connecting clients, clients download it to memory to not require filesystem usage 
  97. unsigned long   g_bsp_compressed_size = 0;  // Server variable
  98. unsigned long   g_prt_compressed_size = 0;  // Server variable
  99. unsigned long   g_bsp_size = 0;             // Server variable
  100. unsigned long   g_prt_size = 0;             // Server variable
  101. #endif
  102.  
  103. #ifdef ZHLT_INFO_COMPILE_PARAMETERS
  104. // AJM: addded in
  105. // =====================================================================================
  106. //  GetParamsFromEnt
  107. //      this function is called from parseentity when it encounters the 
  108. //      info_compile_parameters entity. each tool should have its own version of this
  109. //      to handle its own specific settings.
  110. // =====================================================================================
  111. void            GetParamsFromEnt(entity_t* mapent)
  112. {
  113.     int iTmp;
  114.  
  115.     Log("\nCompile Settings detected from info_compile_parameters entity\n");
  116.  
  117.     // verbose(choices) : "Verbose compile messages" : 0 = [ 0 : "Off" 1 : "On" ]
  118.     iTmp = IntForKey(mapent, "verbose");
  119.     if (iTmp == 1)
  120.     {
  121.         g_verbose = true;
  122.     }
  123.     else if (iTmp == 0)
  124.     {
  125.         g_verbose = false;
  126.     }
  127.     Log("%30s [ %-9s ]\n", "Compile Option", "setting");
  128.     Log("%30s [ %-9s ]\n", "Verbose Compile Messages", g_verbose ? "on" : "off");
  129.  
  130.     // estimate(choices) :"Estimate Compile Times?" : 0 = [ 0: "Yes" 1: "No" ]
  131.     if (IntForKey(mapent, "estimate")) 
  132.     {
  133.         g_estimate = true;
  134.     }
  135.     else
  136.     {
  137.         g_estimate = false;
  138.     }
  139.     Log("%30s [ %-9s ]\n", "Estimate Compile Times", g_estimate ? "on" : "off");
  140.  
  141.     // priority(choices) : "Priority Level" : 0 = [    0 : "Normal" 1 : "High"    -1 : "Low" ]
  142.     if (!strcmp(ValueForKey(mapent, "priority"), "1"))
  143.     {
  144.         g_threadpriority = eThreadPriorityHigh;
  145.         Log("%30s [ %-9s ]\n", "Thread Priority", "high");
  146.     }
  147.     else if (!strcmp(ValueForKey(mapent, "priority"), "-1"))
  148.     {
  149.         g_threadpriority = eThreadPriorityLow;
  150.         Log("%30s [ %-9s ]\n", "Thread Priority", "low");
  151.     }
  152.  
  153.     /*
  154.     hlvis(choices) : "HLVIS" : 2 = 
  155.     [ 
  156.         0 : "Off"
  157.         1 : "Fast"
  158.         2 : "Normal" 
  159.         3 : "Full"
  160.     ]
  161.     */
  162.     iTmp = IntForKey(mapent, "hlvis");
  163.     if (iTmp == 0)
  164.     {
  165.         Fatal(assume_TOOL_CANCEL, 
  166.             "%s flag was not checked in info_compile_parameters entity, execution of %s cancelled", g_Program, g_Program);
  167.         CheckFatal();   
  168.     }
  169.     else if (iTmp == 1)
  170.     {
  171.         g_fastvis = true;
  172.         g_fullvis = false;
  173.     }
  174.     else if (iTmp == 2)
  175.     {
  176.         g_fastvis = false;
  177.         g_fullvis = false;
  178.     }
  179.     else if (iTmp == 3)
  180.     {
  181.         g_fullvis = true;
  182.         g_fastvis = false;
  183.     }
  184.     Log("%30s [ %-9s ]\n", "Fast VIS", g_fastvis ? "on" : "off"); 
  185.     Log("%30s [ %-9s ]\n", "Full VIS", g_fullvis ? "on" : "off" );
  186.  
  187.     ///////////////////
  188.     Log("\n");
  189. }
  190. #endif
  191.  
  192. // =====================================================================================
  193. //  PlaneFromWinding
  194. // =====================================================================================
  195. static void     PlaneFromWinding(winding_t* w, plane_t* plane)
  196. {
  197.     vec3_t          v1;
  198.     vec3_t          v2;
  199.  
  200.     // calc plane
  201.     VectorSubtract(w->points[2], w->points[1], v1);
  202.     VectorSubtract(w->points[0], w->points[1], v2);
  203.     CrossProduct(v2, v1, plane->normal);
  204.     VectorNormalize(plane->normal);
  205.     plane->dist = DotProduct(w->points[0], plane->normal);
  206. }
  207.  
  208. // =====================================================================================
  209. //  NewWinding
  210. // =====================================================================================
  211. static winding_t* NewWinding(const int points)
  212. {
  213.     winding_t*      w;
  214.     int             size;
  215.  
  216.     if (points > MAX_POINTS_ON_WINDING)
  217.     {
  218.         Error("NewWinding: %i points > MAX_POINTS_ON_WINDING", points);
  219.     }
  220.  
  221.     size = (int)((winding_t*)0)->points[points];
  222.     w = (winding_t*)calloc(1, size);
  223.  
  224.     return w;
  225. }
  226.  
  227. //=============================================================================
  228.  
  229. /////////
  230. // NETVIS
  231. #ifdef ZHLT_NETVIS
  232.  
  233. // =====================================================================================
  234. //  GetPortalPtr
  235. //      converts a portal index to a pointer
  236. // =====================================================================================
  237. portal_t*       GetPortalPtr(const long index)
  238. {
  239.     if (index < (g_numportals * 2))
  240.     {
  241.         return g_portals + index;
  242.     }
  243.     else
  244.     {
  245.         return (NULL);
  246.     }
  247. }
  248.  
  249.  
  250. // =====================================================================================
  251. //  GetNextPortalIndex
  252. //      This is called by ClientSockets
  253. // =====================================================================================
  254. int             GetNextPortalIndex()
  255. {
  256.     int             j;
  257.     int             best = NO_PORTAL_INDEX;
  258.     portal_t*       p;
  259.     portal_t*       tp;
  260.     int             min;
  261.  
  262.     ThreadLock();
  263.  
  264.     min = 99999;
  265.     p = NULL;
  266.  
  267.     for (j = 0, tp = g_portals; j < g_numportals * 2; j++, tp++)
  268.     {
  269.         if (tp->nummightsee < min && tp->status == stat_none)
  270.         {
  271.             min = tp->nummightsee;
  272.             p = tp;
  273.             best = j;
  274.         }
  275.     }
  276.  
  277.     if (p)
  278.     {
  279.         p->status = stat_working;
  280.     }
  281.     else
  282.     {
  283.         best = NO_PORTAL_INDEX;                            // hack to return NO_PORTAL_INDEX to the queue'ing code
  284.     }
  285.  
  286.     ThreadUnlock();
  287.  
  288.     return best;
  289. }
  290.  
  291. // =====================================================================================
  292. //  AllPortalsDone
  293. //      returns true if all portals are done...
  294. // =====================================================================================
  295. static int      AllPortalsDone()
  296. {
  297.     const unsigned  numportals = g_numportals * 2;
  298.     portal_t*       tp;
  299.  
  300.     unsigned        j;
  301.     for (j = 0, tp = g_portals; j < numportals; j++, tp++)
  302.     {
  303.         if (tp->status != stat_done)
  304.         {
  305.             return 0;
  306.         }
  307.     }
  308.  
  309.     return 1;
  310. }
  311.  
  312. #endif
  313. // NETVIS
  314. ///////////
  315.  
  316. // =====================================================================================
  317. //  GetNextPortal
  318. //      Returns the next portal for a thread to work on
  319. //      Returns the portals from the least complex, so the later ones can reuse the earlier information.
  320. // =====================================================================================
  321. static portal_t* GetNextPortal()
  322. {
  323.     int             j;
  324.     portal_t*       p;
  325.     portal_t*       tp;
  326.     int             min;
  327.  
  328. #ifdef ZHLT_NETVIS
  329.     if (g_vismode == VIS_MODE_SERVER)
  330.     {
  331. #else
  332.     {
  333.         if (GetThreadWork() == -1)
  334.         {
  335.             return NULL;
  336.         }
  337. #endif
  338.         ThreadLock();
  339.  
  340.         min = 99999;
  341.         p = NULL;
  342.  
  343.         for (j = 0, tp = g_portals; j < g_numportals * 2; j++, tp++)
  344.         {
  345.             if (tp->nummightsee < min && tp->status == stat_none)
  346.             {
  347.                 min = tp->nummightsee;
  348.                 p = tp;
  349. #ifdef ZHLT_NETVIS
  350.                 g_visportalindex = j;
  351. #endif
  352.             }
  353.         }
  354.  
  355.         if (p)
  356.         {
  357.             p->status = stat_working;
  358.         }
  359.  
  360.         ThreadUnlock();
  361.  
  362.         return p;
  363.     }
  364. #ifdef ZHLT_NETVIS
  365.     else                                                   // AS CLIENT
  366.     {
  367.         while (getWorkFromClientQueue() == WAITING_FOR_PORTAL_INDEX)
  368.         {
  369.             unsigned        delay = 100;
  370.  
  371.             g_idletime += delay;                           // This is the only point where the portal work goes idle, so its easy to add up just how idle it is.
  372.             if (!isConnectedToServer())
  373.             {
  374.                 Error("Unexepected disconnect from server(1)\n");
  375.             }
  376.             NetvisSleep(delay);
  377.         }
  378.  
  379.         if (g_visportalindex == NO_PORTAL_INDEX)
  380.         {
  381.             g_visstate = VIS_CLIENT_DONE;
  382.             Send_VIS_GOING_DOWN(g_ClientSession);
  383.             return NULL;
  384.         }
  385.  
  386.         // convert index to pointer
  387.         tp = GetPortalPtr(g_visportalindex);
  388.  
  389.         if (tp)
  390.         {
  391.             tp->status = stat_working;
  392.         }
  393.         return (tp);
  394.     }
  395. #endif
  396. }
  397.  
  398. #ifdef HLVIS_MAXDIST
  399.  
  400. // AJM: MVD
  401. // =====================================================================================
  402. //  DecompressAll
  403. // =====================================================================================
  404. void            DecompressAll(void)
  405. {
  406.     int i;
  407.     byte *dest;
  408.  
  409.     for(i = 0; i < g_portalleafs; i++)
  410.     {
  411.         dest = g_uncompressed + i * g_bitbytes;
  412.  
  413.         DecompressVis((const unsigned char*)(g_dvisdata + (byte)g_dleafs[i + 1].visofs), dest, g_bitbytes);
  414.     }
  415. }
  416.  
  417. // AJM: MVD
  418. // =====================================================================================
  419. //  CompressAll
  420. // =====================================================================================
  421. void            CompressAll(void)
  422. {
  423.     int i, x = 0;
  424.     byte *dest;
  425.     byte *src;
  426.     byte    compressed[MAX_MAP_LEAFS / 8];
  427.  
  428.     vismap_p = vismap;
  429.     
  430.     for(i = 0; i < g_portalleafs; i++)
  431.     {
  432.         memset(&compressed, 0, sizeof(compressed));
  433.  
  434.         src = g_uncompressed + i * g_bitbytes;
  435.         
  436.         // Compress all leafs into global compression buffer
  437.         x = CompressVis(src, g_bitbytes, compressed, sizeof(compressed));
  438.  
  439.         dest = vismap_p;
  440.         vismap_p += x;
  441.  
  442.         if (vismap_p > vismap_end)
  443.         {
  444.             Error("Vismap expansion overflow");
  445.         }
  446.     
  447.         g_dleafs[i + 1].visofs = dest - vismap;            // leaf 0 is a common solid
  448.  
  449.         memcpy(dest, compressed, x);
  450.     }
  451. }
  452.  
  453. #endif // HLVIS_MAXDIST
  454.  
  455. // =====================================================================================
  456. //  LeafThread
  457. // =====================================================================================
  458. #ifdef SYSTEM_WIN32
  459. #pragma warning(push)
  460. #pragma warning(disable: 4100)                             // unreferenced formal parameter
  461. #endif
  462.  
  463. #ifndef ZHLT_NETVIS
  464. static void     LeafThread(int unused)
  465. {
  466.     portal_t*       p;
  467.  
  468.     while (1)
  469.     {
  470.         if (!(p = GetNextPortal()))
  471.         {
  472.             return;
  473.         }
  474.  
  475.         PortalFlow(p);
  476.  
  477.         Verbose("portal:%4i  mightsee:%4i  cansee:%4i\n", (int)(p - g_portals), p->nummightsee, p->numcansee);
  478.     }
  479. }
  480. #endif //!ZHLT_NETVIS
  481.  
  482. #ifdef ZHLT_NETVIS
  483.  
  484. static void     LeafThread(int unused)
  485. {
  486.     if (g_vismode == VIS_MODE_CLIENT)
  487.     {
  488.         portal_t*       p;
  489.  
  490.         g_visstate = VIS_BASE_PORTAL_VIS_SERVER_WAIT;
  491.         Send_VIS_LEAFTHREAD(g_visleafs, g_visportals, g_bitbytes);
  492.         while (!g_visleafthread)
  493.         {
  494.             if (!isConnectedToServer())
  495.             {
  496.                 Error("Unexepected disconnect from server(2)\n");
  497.             }
  498.             NetvisSleep(100);
  499.         }
  500.         g_visstate = VIS_PORTAL_FLOW;
  501.         Send_VIS_WANT_FULL_SYNC();
  502.  
  503.         while (!g_NetvisAbort)
  504.         {
  505.             if (!(p = GetNextPortal()))
  506.             {
  507.                 return;
  508.             }
  509.  
  510.             PortalFlow(p);
  511.             Send_VIS_DONE_PORTAL(g_visportalindex, p);
  512.             g_vislocalportal++;
  513.         }
  514.     }
  515.     else if (g_vismode == VIS_MODE_SERVER)
  516.     {
  517. #if 0
  518.         // Server does zero work in ZHLT netvis
  519.         g_visstate = VIS_WAIT_CLIENTS;
  520.         while (!g_NetvisAbort)
  521.         {
  522.             NetvisSleep(1000);
  523.             if (AllPortalsDone())
  524.             {
  525.                 g_visstate = VIS_POST;
  526.                 return;
  527.             }
  528.         }
  529. #else
  530.         portal_t*       p;
  531.  
  532.         g_visstate = VIS_WAIT_CLIENTS;
  533.         while (!g_NetvisAbort)
  534.         {
  535.             if (!(p = GetNextPortal()))
  536.             {
  537.                 if (AllPortalsDone())
  538.                 {
  539.                     g_visstate = VIS_POST;
  540.                     return;
  541.                 }
  542.                 NetvisSleep(1000);                         // No need to churn while waiting on slow clients
  543.                 continue;
  544.             }
  545.             PortalFlow(p);
  546.             g_vislocalportal++;
  547.         }
  548. #endif
  549.     }
  550.     else
  551.     {
  552.         hlassume(false, assume_VALID_NETVIS_STATE);
  553.     }
  554. }
  555. #endif
  556.  
  557. #ifdef SYSTEM_WIN32
  558. #pragma warning(pop)
  559. #endif
  560.  
  561. // =====================================================================================
  562. //  LeafFlow
  563. //      Builds the entire visibility list for a leaf
  564. // =====================================================================================
  565. static void     LeafFlow(const int leafnum)
  566. {
  567.     leaf_t*         leaf;
  568.     byte*           outbuffer;
  569.     byte            compressed[MAX_MAP_LEAFS / 8];
  570.     unsigned        i;
  571.     unsigned        j;
  572.     int             k;
  573.     int             tmp;
  574.     int             numvis;
  575.     byte*           dest;
  576.     portal_t*       p;
  577.  
  578.     //
  579.     // flow through all portals, collecting visible bits
  580.     //
  581.     memset(compressed, 0, sizeof(compressed));
  582.     outbuffer = g_uncompressed + leafnum * g_bitbytes;
  583.     leaf = &g_leafs[leafnum];
  584.     tmp = 0;
  585.  
  586.     const unsigned offset = leafnum >> 3;
  587.     const unsigned bit = (1 << (leafnum & 7));
  588.  
  589.     for (i = 0; i < leaf->numportals; i++)
  590.     {
  591.         p = leaf->portals[i];
  592.         if (p->status != stat_done)
  593.         {
  594.             Error("portal not done (leaf %d)", leafnum);
  595.         }
  596.  
  597.         {
  598.             byte* dst = outbuffer;
  599.             byte* src = p->visbits;
  600.             for (j=0; j<g_bitbytes; j++, dst++, src++)
  601.             {
  602.                 *dst |= *src;
  603.             }
  604.         }
  605.  
  606.         if ((tmp == 0) && (outbuffer[offset] & bit))
  607.         {
  608.             tmp = 1;
  609.             Warning("Leaf portals saw into leaf");
  610.             Log("    Problem at portal between leaves %i and %i:\n   ", leafnum, p->leaf);
  611.             for (k = 0; k < p->winding->numpoints; k++)
  612.             {
  613.                 Log("    (%4.3f %4.3f %4.3f)\n", p->winding->points[k][0], p->winding->points[k][1], p->winding->points[k][2]);
  614.             }
  615.             Log("\n");
  616.         }
  617.     }
  618.  
  619.     outbuffer[offset] |= bit;
  620.  
  621.     numvis = 0;
  622.     for (i = 0; i < g_portalleafs; i++)
  623.     {
  624.         if (outbuffer[i >> 3] & (1 << (i & 7)))
  625.         {
  626.             numvis++;
  627.         }
  628.     }
  629.  
  630.     //
  631.     // compress the bit string
  632.     //
  633.     Verbose("leaf %4i : %4i visible\n", leafnum, numvis);
  634.     totalvis += numvis;
  635.  
  636.     i = CompressVis(outbuffer, g_bitbytes, compressed, sizeof(compressed));
  637.  
  638.     dest = vismap_p;
  639.     vismap_p += i;
  640.  
  641.     if (vismap_p > vismap_end)
  642.     {
  643.         Error("Vismap expansion overflow");
  644.     }
  645.  
  646.     g_dleafs[leafnum + 1].visofs = dest - vismap;            // leaf 0 is a common solid
  647.  
  648.     memcpy(dest, compressed, i);
  649. }
  650.  
  651. // =====================================================================================
  652. //  CalcPortalVis
  653. // =====================================================================================
  654. static void     CalcPortalVis()
  655. {
  656. #ifndef ZHLT_NETVIS
  657.     // g_fastvis just uses mightsee for a very loose bound
  658.     if (g_fastvis)
  659.     {
  660.         int             i;
  661.  
  662.         for (i = 0; i < g_numportals * 2; i++)
  663.         {
  664.             g_portals[i].visbits = g_portals[i].mightsee;
  665.             g_portals[i].status = stat_done;
  666.         }
  667.         return;
  668.     }
  669. #endif
  670.  
  671. #ifdef ZHLT_NETVIS
  672.     LeafThread(0);
  673. #else
  674.     NamedRunThreadsOn(g_numportals * 2, g_estimate, LeafThread);
  675. #endif
  676. }
  677.  
  678. //////////////
  679. // ZHLT_NETVIS
  680.  
  681. #ifdef ZHLT_NETVIS
  682. // =====================================================================================
  683. //  CalcVis
  684. // =====================================================================================
  685. static void     CalcVis()
  686. {
  687.     unsigned        lastpercent = 0;
  688.     int             x, size;
  689.  
  690.     if (g_vismode == VIS_MODE_SERVER)
  691.     {
  692.         g_visstate = VIS_BASE_PORTAL_VIS;
  693.         Log("BasePortalVis: \n");
  694.         
  695.         for (x = 0, size = g_numportals * 2; x < size; x++)
  696.         {
  697.             unsigned        percent = (x * 100 / size);
  698.             
  699.             if (percent && (percent != lastpercent) && ((percent % 10) == 0))
  700.             {
  701.                 lastpercent = percent;
  702.                 printf("%d%%....", percent);
  703.             }
  704.             BasePortalVis(x);
  705.         }
  706.         printf("\n");
  707.     }
  708.     else
  709.     {
  710.         Send_VIS_WANT_MIGHTSEE_DATA();
  711.         while(!g_mightsee_downloaded)
  712.         {
  713.             if (!isConnectedToServer())
  714.             {
  715.                 Error("Unexepected disconnect from server(3)\n");
  716.             }
  717.             NetvisSleep(100);
  718.         }
  719.     }
  720.  
  721.     g_visportals = g_numportals;
  722.     g_visleafs = g_portalleafs;
  723.  
  724.     g_starttime = I_FloatTime();
  725.     StartStatusDisplayThread(g_rate);
  726.     CalcPortalVis();
  727.  
  728.     if (g_vismode == VIS_MODE_SERVER)
  729.     {
  730.         unsigned int    i;
  731.  
  732.         for (i = 0; i < g_portalleafs; i++)
  733.         {
  734.             LeafFlow(i);
  735.         }
  736.  
  737.         Log("average leafs visible: %i\n", totalvis / g_portalleafs);
  738.     }
  739. }
  740. #endif
  741.  
  742. #ifndef ZHLT_NETVIS
  743.  
  744. #ifdef HLVIS_MAXDIST
  745. // AJM: MVD
  746. // =====================================================================================
  747. //  GetVisBlock
  748. // =====================================================================================
  749. visblocker_t *GetVisBlock(char *name)
  750. {
  751.     int i;
  752.     visblocker_t *v;
  753.  
  754.     for(i = 0, v = &g_visblockers[0]; i < g_numvisblockers; i++, v++)
  755.     {
  756.         if(!strcmp(name, v->name))
  757.             return v;
  758.     }
  759.  
  760.     return NULL;
  761. }
  762.  
  763. // AJM: MVD
  764. // =====================================================================================
  765. //  InitVisBlock
  766. // =====================================================================================
  767. static void InitVisBlock(void)
  768. {
  769.     char visfile[_MAX_PATH];
  770.     int i;
  771.     int x = 0;
  772.     int num_blocks;
  773.     int num_sides;
  774.  
  775.     strcpy(visfile, g_Mapname);
  776.     DefaultExtension(visfile, ".vis");
  777.  
  778.     if(!q_exists(visfile))
  779.         return;
  780.  
  781.     FILE *fp = fopen(visfile, "r");
  782.  
  783.     if(!fp)
  784.         return;
  785.  
  786.     while(!feof(fp))
  787.     {
  788.         fscanf(fp, "%s\n", g_visblockers[x].name);
  789.  
  790.         fscanf(fp, "%d\n", &num_blocks);
  791.         
  792.         for(i = 0; i < num_blocks; i++)
  793.         {
  794.             fscanf(fp, "%s\n", g_visblockers[x].blocknames[i]);
  795.         }
  796.  
  797.         g_visblockers[x].numnames = num_blocks;
  798.  
  799.         fscanf(fp, "%d\n", &num_sides);
  800.  
  801.         for(i = 0; i < num_sides; i++)
  802.         {
  803.             fscanf(fp, "%f %f %f %f\n", &g_visblockers[x].planes[i].normal[0],
  804.                                         &g_visblockers[x].planes[i].normal[1],
  805.                                         &g_visblockers[x].planes[i].normal[2],
  806.                                         &g_visblockers[x].planes[i].dist);
  807.         }
  808.  
  809.         g_visblockers[x].numplanes = num_sides;
  810.         g_visblockers[x].numleafs = 0;
  811.  
  812.         x++;
  813.     }
  814.  
  815.     g_numvisblockers = x;
  816. }
  817.  
  818. // AJM: MVD
  819. // =====================================================================================
  820. //  SetupVisBlockLeafs
  821. //      Set up the leafs for the visblocker
  822. // =====================================================================================
  823. static void        SetupVisBlockLeafs(void)
  824. {
  825.     int i, j, k, l, q;
  826.     visblocker_t *v;
  827.     leaf_t *leaf;
  828.     portal_t *p;
  829.     plane_t *plane;
  830.     float dist;
  831.  
  832.     for(i = 0, v = &g_visblockers[0]; i < g_numvisblockers; i++, v++)
  833.     {
  834.         for(j = 0, leaf = &g_leafs[0]; j < g_portalleafs; j++, leaf++)
  835.         {
  836.             for(q = 0, p = leaf->portals[0]; q < leaf->numportals; q++, p++)
  837.             {
  838.                 for(k = 0; k < p->winding->numpoints; k++)
  839.                 {
  840.                     for(l = 0, plane = &v->planes[0]; l < v->numplanes; l++, plane++)
  841.                     {
  842.                         dist = DotProduct(p->winding->points[k], plane->normal) - plane->dist;
  843.     
  844.                         if(dist > ON_EPSILON)
  845.                             goto PostLoop;
  846.                     }
  847.                 }
  848.             }
  849.  
  850. PostLoop:
  851.             if(q != leaf->numportals)
  852.                 continue;
  853.  
  854.             // If we reach this point, then the portal is completely inside the visblocker
  855.             v->blockleafs[v->numleafs++] = j;
  856.         }
  857.     }
  858. }
  859.  
  860. // AJM: MVD
  861. // =====================================================================================
  862. //  SaveVisData
  863. // =====================================================================================
  864. void        SaveVisData(const char *filename)
  865. {
  866.     int i;
  867.     FILE *fp = fopen(filename, "wb");
  868.  
  869.     if(!fp)
  870.         return;
  871.  
  872.     SafeWrite(fp, g_dvisdata, (vismap_p - g_dvisdata));
  873.  
  874.     // BUG BUG BUG!
  875.     // Leaf offsets need to be saved too!!!!
  876.     for(i = 0; i < g_numleafs; i++)
  877.     {
  878.         SafeWrite(fp, &g_dleafs[i].visofs, sizeof(int));
  879.     }
  880.  
  881.     fclose(fp);
  882. }
  883.  
  884. // AJM: MVD
  885. // =====================================================================================
  886. //  ResetPortalStatus
  887. //      FIX: Used to reset p->status to stat_none; now it justs frees p->visbits
  888. // =====================================================================================
  889. void        ResetPortalStatus(void)
  890. {
  891.     int i;
  892.     portal_t* p = g_portals;
  893.  
  894.     for(i = 0; i < g_numportals * 2; i++, p++)
  895.     {
  896.         //p->status = stat_none;
  897.         free(p->visbits);
  898.     }
  899. }
  900.  
  901. #endif // HLVIS_MAXDIST
  902.  
  903.  
  904. // AJM UNDONE HLVIS_MAXDIST THIS!!!!!!!!!!!!!
  905.  
  906. // AJM: MVD modified
  907. // =====================================================================================
  908. //  CalcVis
  909. // =====================================================================================
  910. static void     CalcVis()
  911. {
  912.     unsigned        i;
  913.     char visdatafile[_MAX_PATH];
  914.  
  915.     strcpy(visdatafile, g_Mapname);
  916.     DefaultExtension(visdatafile, ".vdt");
  917.  
  918.     // Remove this file
  919.     unlink(visdatafile);
  920.  
  921. /*    if(g_postcompile)
  922.     {
  923.         if(!g_maxdistance)
  924.         {
  925.             Error("Must use -maxdistance parameter with -postcompile");
  926.         }
  927.  
  928.         // Decompress everything so we can edit it
  929.         DecompressAll();
  930.         
  931.         NamedRunThreadsOn(g_portalleafs, g_estimate, PostMaxDistVis);
  932.  
  933.         // Recompress it
  934.         CompressAll();
  935.     }
  936.     else
  937.     {*/
  938. //        InitVisBlock();
  939. //        SetupVisBlockLeafs();
  940.  
  941.         NamedRunThreadsOn(g_numportals * 2, g_estimate, BasePortalVis);
  942.  
  943. //        if(g_numvisblockers)
  944. //            NamedRunThreadsOn(g_numvisblockers, g_estimate, BlockVis);
  945.  
  946.         // First do a normal VIS, save to file, then redo MaxDistVis
  947.  
  948.         CalcPortalVis();
  949.  
  950.         //
  951.         // assemble the leaf vis lists by oring and compressing the portal lists
  952.         //
  953.         for (i = 0; i < g_portalleafs; i++)
  954.         {
  955.             LeafFlow(i);
  956.         }
  957.  
  958.         Log("average leafs visible: %i\n", totalvis / g_portalleafs);
  959.  
  960.         if(g_maxdistance)
  961.         {
  962.             totalvis = 0;
  963.             
  964.             Log("saving visdata to %s...\n", visdatafile);
  965.             SaveVisData(visdatafile);
  966.  
  967.             // We need to reset the uncompressed variable and portal visbits
  968.             free(g_uncompressed);
  969.             g_uncompressed = (byte*)calloc(g_portalleafs, g_bitbytes);
  970.  
  971.             vismap_p = g_dvisdata;
  972.  
  973.             // We don't need to run BasePortalVis again            
  974.             NamedRunThreadsOn(g_portalleafs, g_estimate, MaxDistVis);
  975.  
  976.             // No need to run this - MaxDistVis now writes directly to visbits after the initial VIS
  977.             //CalcPortalVis();
  978.         
  979.             for (i = 0; i < g_portalleafs; i++)
  980.             {
  981.                 LeafFlow(i);
  982.             }
  983.  
  984.             // FIX: Used to reset p->status to stat_none; now it justs frees p->visbits
  985.             ResetPortalStatus();
  986.  
  987.             Log("average maxdistance leafs visible: %i\n", totalvis / g_portalleafs);
  988.         }
  989. //    }
  990. }
  991. #endif //!ZHLT_NETVIS
  992.  
  993. // ZHLT_NETVIS
  994. //////////////
  995.  
  996. // =====================================================================================
  997. //  CheckNullToken
  998. // =====================================================================================
  999. static INLINE void FASTCALL CheckNullToken(const char*const token)
  1000. {
  1001.     if (token == NULL) 
  1002.     {
  1003.         Error("LoadPortals: Damaged or invalid .prt file\n");
  1004.     }
  1005. }
  1006.  
  1007. // =====================================================================================
  1008. //  LoadPortals
  1009. // =====================================================================================
  1010. static void     LoadPortals(char* portal_image)
  1011. {
  1012.     int             i, j;
  1013.     portal_t*       p;
  1014.     leaf_t*         l;
  1015.     int             numpoints;
  1016.     winding_t*      w;
  1017.     int             leafnums[2];
  1018.     plane_t         plane;
  1019.     const char* const seperators = " ()\r\n\t";
  1020.     char*           token;
  1021.  
  1022.     token = strtok(portal_image, seperators);
  1023.     CheckNullToken(token);
  1024.     if (!sscanf(token, "%u", &g_portalleafs))
  1025.     {
  1026.         Error("LoadPortals: failed to read header: number of leafs");
  1027.     }
  1028.  
  1029.     token = strtok(NULL, seperators);
  1030.     CheckNullToken(token);
  1031.     if (!sscanf(token, "%i", &g_numportals))
  1032.     {
  1033.         Error("LoadPortals: failed to read header: number of portals");
  1034.     }
  1035.     
  1036.     Log("%4i portalleafs\n", g_portalleafs);
  1037.     Log("%4i numportals\n", g_numportals);
  1038.  
  1039.     g_bitbytes = ((g_portalleafs + 63) & ~63) >> 3;
  1040.     g_bitlongs = g_bitbytes / sizeof(long);
  1041.  
  1042.     // each file portal is split into two memory portals
  1043.     g_portals = (portal_t*)calloc(2 * g_numportals, sizeof(portal_t));
  1044.     g_leafs = (leaf_t*)calloc(g_portalleafs, sizeof(leaf_t));
  1045.  
  1046.     originalvismapsize = g_portalleafs * ((g_portalleafs + 7) / 8);
  1047.  
  1048.     vismap = vismap_p = g_dvisdata;
  1049.     vismap_end = vismap + MAX_MAP_VISIBILITY;
  1050.  
  1051.     for (i = 0, p = g_portals; i < g_numportals; i++)
  1052.     {
  1053.         unsigned rval = 0;
  1054.  
  1055.         token = strtok(NULL, seperators);
  1056.         CheckNullToken(token);
  1057.         rval += sscanf(token, "%i", &numpoints);
  1058.         token = strtok(NULL, seperators);
  1059.         CheckNullToken(token);
  1060.         rval += sscanf(token, "%i", &leafnums[0]);
  1061.         token = strtok(NULL, seperators);
  1062.         CheckNullToken(token);
  1063.         rval += sscanf(token, "%i", &leafnums[1]);
  1064.  
  1065.         if (rval != 3)
  1066.         {
  1067.             Error("LoadPortals: reading portal %i", i);
  1068.         }
  1069.         if (numpoints > MAX_POINTS_ON_WINDING)
  1070.         {
  1071.             Error("LoadPortals: portal %i has too many points", i);
  1072.         }
  1073.         if (((unsigned)leafnums[0] > g_portalleafs) || ((unsigned)leafnums[1] > g_portalleafs))
  1074.         {
  1075.             Error("LoadPortals: reading portal %i", i);
  1076.         }
  1077.  
  1078.         w = p->winding = NewWinding(numpoints);
  1079.         w->original = true;
  1080.         w->numpoints = numpoints;
  1081.  
  1082.         for (j = 0; j < numpoints; j++)
  1083.         {
  1084.             int             k;
  1085.             double          v[3];
  1086.             unsigned        rval = 0;
  1087.  
  1088.             token = strtok(NULL, seperators);
  1089.             CheckNullToken(token);
  1090.             rval += sscanf(token, "%lf", &v[0]);
  1091.             token = strtok(NULL, seperators);
  1092.             CheckNullToken(token);
  1093.             rval += sscanf(token, "%lf", &v[1]);
  1094.             token = strtok(NULL, seperators);
  1095.             CheckNullToken(token);
  1096.             rval += sscanf(token, "%lf", &v[2]);
  1097.  
  1098.             // scanf into double, then assign to vec_t
  1099.             if (rval != 3)
  1100.             {
  1101.                 Error("LoadPortals: reading portal %i", i);
  1102.             }
  1103.             for (k = 0; k < 3; k++)
  1104.             {
  1105.                 w->points[j][k] = v[k];
  1106.             }
  1107.         }
  1108.  
  1109.         // calc plane
  1110.         PlaneFromWinding(w, &plane);
  1111.  
  1112.         // create forward portal
  1113.         l = &g_leafs[leafnums[0]];
  1114.         hlassume(l->numportals < MAX_PORTALS_ON_LEAF, assume_MAX_PORTALS_ON_LEAF);
  1115.         l->portals[l->numportals] = p;
  1116.         l->numportals++;
  1117.  
  1118.         p->winding = w;
  1119.         VectorSubtract(vec3_origin, plane.normal, p->plane.normal);
  1120.         p->plane.dist = -plane.dist;
  1121.         p->leaf = leafnums[1];
  1122.         p++;
  1123.  
  1124.         // create backwards portal
  1125.         l = &g_leafs[leafnums[1]];
  1126.         hlassume(l->numportals < MAX_PORTALS_ON_LEAF, assume_MAX_PORTALS_ON_LEAF);
  1127.         l->portals[l->numportals] = p;
  1128.         l->numportals++;
  1129.  
  1130.         p->winding = NewWinding(w->numpoints);
  1131.         p->winding->numpoints = w->numpoints;
  1132.         for (j = 0; j < w->numpoints; j++)
  1133.         {
  1134.             VectorCopy(w->points[w->numpoints - 1 - j], p->winding->points[j]);
  1135.         }
  1136.  
  1137.         p->plane = plane;
  1138.         p->leaf = leafnums[0];
  1139.         p++;
  1140.  
  1141.     }
  1142. }
  1143.  
  1144. // =====================================================================================
  1145. //  LoadPortalsByFilename
  1146. // =====================================================================================
  1147. static void     LoadPortalsByFilename(const char* const filename)
  1148. {
  1149.     char* file_image;
  1150.  
  1151.     if (!q_exists(filename))
  1152.     {
  1153.         Error("Portal file '%s' does not exist, cannot vis the map\n", filename);
  1154.     }
  1155.     LoadFile(filename, &file_image);
  1156.     LoadPortals(file_image);
  1157.     free(file_image);
  1158. }
  1159.  
  1160.  
  1161. #if ZHLT_ZONES
  1162. // =====================================================================================
  1163. //  AssignPortalsToZones
  1164. // =====================================================================================
  1165. static void     AssignPortalsToZones()
  1166. {
  1167.     hlassert(g_Zones != NULL);
  1168.  
  1169.     UINT32 count = 0;
  1170.  
  1171.     portal_t* p;
  1172.     UINT32 x;
  1173.  
  1174.     UINT32 tmp[20];
  1175.     memset(tmp, 0, sizeof(tmp));
  1176.  
  1177.     UINT32 numportals = g_numportals * 2;
  1178.     for (x=0, p=g_portals; x<numportals; x++, p++)
  1179.     {
  1180.         BoundingBox bounds;
  1181.         winding_t* w = p->winding;
  1182.         UINT32 numpoints = w->numpoints;
  1183.  
  1184.         UINT32 y;
  1185.  
  1186.         for (y=0; y<numpoints; y++)
  1187.         {
  1188.             bounds.add(w->points[y]);
  1189.         }
  1190.  
  1191.         p->zone = g_Zones->getZoneFromBounds(bounds);
  1192.         tmp[p->zone]++;
  1193.         if (p->zone)
  1194.         {
  1195.             count++;
  1196.         }
  1197.     }
  1198.  
  1199.     for (x=0; x<15; x++)
  1200.     {
  1201.         Log("Zone %2u : %u\n", x, tmp[x]);
  1202.     }
  1203.     Log("%u of %u portals were contained in func_vis zones\n", count, numportals);
  1204. }
  1205. #endif
  1206.  
  1207. // =====================================================================================
  1208. //  Usage
  1209. // =====================================================================================
  1210. static void     Usage()
  1211. {
  1212.     Banner();
  1213.  
  1214.     Log("\n-= %s Options =-\n\n", g_Program);
  1215.     Log("    -full           : Full vis\n");
  1216.     Log("    -fast           : Fast vis\n\n");
  1217. #ifdef ZHLT_NETVIS
  1218.     Log("    -connect address : Connect to netvis server at address as a client\n");
  1219.     Log("    -server          : Run as the netvis server\n");
  1220.     Log("    -port #          : Use a non-standard port for netvis\n");
  1221.     Log("    -rate #          : Alter the display update rate\n\n");
  1222. #endif
  1223.     Log("    -texdata #      : Alter maximum texture memory limit (in kb)\n");
  1224.     Log("    -chart          : display bsp statitics\n");
  1225.     Log("    -low | -high    : run program an altered priority level\n");
  1226.     Log("    -nolog          : don't generate the compile logfiles\n");
  1227.     Log("    -threads #      : manually specify the number of threads to run\n");
  1228. #ifdef SYSTEM_WIN32
  1229.     Log("    -estimate       : display estimated time during compile\n");
  1230. #endif
  1231. #ifdef ZHLT_PROGRESSFILE // AJM
  1232.     Log("    -progressfile path  : specify the path to a file for progress estimate output\n");
  1233. #endif
  1234. #ifdef SYSTEM_POSIX
  1235.     Log("    -noestimate     : do not display continuous compile time estimates\n");
  1236. #endif
  1237. #ifdef HLVIS_MAXDIST // AJM: MVD
  1238.     Log("    -maxdistance #  : Alter the maximum distance for visibility\n");
  1239. #endif
  1240.     Log("    -verbose        : compile with verbose messages\n");
  1241.     Log("    -noinfo         : Do not show tool configuration information\n");
  1242.     Log("    -dev #          : compile with developer message\n\n");
  1243.     Log("    mapfile         : The mapfile to compile\n\n");
  1244.  
  1245. #ifdef ZHLT_NETVIS
  1246.     Log("\n"
  1247.         "In netvis one computer must be the server and all the rest are the clients.\n"
  1248.         "The server should be started with      : netvis -server mapname\n"
  1249.         "And the clients should be started with : netvis -connect servername\n"
  1250.         "\n"
  1251.         "The default socket it uses is 21212 and can be changed with -port\n"
  1252.         "The default update rate is 60 seconds and can be changed with -rate\n");
  1253.  
  1254. #endif
  1255.  
  1256.     exit(1);
  1257. }
  1258.  
  1259. // =====================================================================================
  1260. //  Settings
  1261. // =====================================================================================
  1262. static void     Settings()
  1263. {
  1264.     char*           tmp;
  1265.  
  1266.     if (!g_info)
  1267.     {
  1268.         return; 
  1269.     }
  1270.  
  1271.     Log("\n-= Current %s Settings =-\n", g_Program);
  1272.     Log("Name               |  Setting  |  Default\n" "-------------------|-----------|-------------------------\n");
  1273.  
  1274.     // ZHLT Common Settings
  1275.     if (DEFAULT_NUMTHREADS == -1)
  1276.     {
  1277.         Log("threads             [ %7d ] [  Varies ]\n", g_numthreads);
  1278.     }
  1279.     else
  1280.     {
  1281.         Log("threads             [ %7d ] [ %7d ]\n", g_numthreads, DEFAULT_NUMTHREADS);
  1282.     }
  1283.  
  1284.     Log("verbose             [ %7s ] [ %7s ]\n", g_verbose ? "on" : "off", DEFAULT_VERBOSE ? "on" : "off");
  1285.     Log("log                 [ %7s ] [ %7s ]\n", g_log ? "on" : "off", DEFAULT_LOG ? "on" : "off");
  1286.     Log("developer           [ %7d ] [ %7d ]\n", g_developer, DEFAULT_DEVELOPER);
  1287.     Log("chart               [ %7s ] [ %7s ]\n", g_chart ? "on" : "off", DEFAULT_CHART ? "on" : "off");
  1288.     Log("estimate            [ %7s ] [ %7s ]\n", g_estimate ? "on" : "off", DEFAULT_ESTIMATE ? "on" : "off");
  1289.     Log("max texture memory  [ %7d ] [ %7d ]\n", g_max_map_miptex, DEFAULT_MAX_MAP_MIPTEX);
  1290.  
  1291. #ifdef HLVIS_MAXDIST // AJM: MVD
  1292.     Log("max vis distance    [ %7d ] [ %7d ]\n", g_maxdistance, DEFAULT_MAXDISTANCE_RANGE);
  1293.     //Log("max dist only       [ %7s ] [ %7s ]\n", g_postcompile ? "on" : "off", DEFAULT_POST_COMPILE ? "on" : "off");
  1294. #endif
  1295.  
  1296.     switch (g_threadpriority)
  1297.     {
  1298.     case eThreadPriorityNormal:
  1299.     default:
  1300.         tmp = "Normal";
  1301.         break;
  1302.     case eThreadPriorityLow:
  1303.         tmp = "Low";
  1304.         break;
  1305.     case eThreadPriorityHigh:
  1306.         tmp = "High";
  1307.         break;
  1308.     }
  1309.     Log("priority            [ %7s ] [ %7s ]\n", tmp, "Normal");
  1310.     Log("\n");
  1311.  
  1312.     // HLVIS Specific Settings
  1313.     Log("fast vis            [ %7s ] [ %7s ]\n", g_fastvis ? "on" : "off", DEFAULT_FASTVIS ? "on" : "off");
  1314.     Log("full vis            [ %7s ] [ %7s ]\n", g_fullvis ? "on" : "off", DEFAULT_FULLVIS ? "on" : "off");
  1315.  
  1316. #ifdef ZHLT_NETVIS
  1317.     if (g_vismode == VIS_MODE_SERVER)
  1318.     {
  1319.         Log("netvis mode         [  Server ]\n");
  1320.     }
  1321.     else if (g_vismode == VIS_MODE_CLIENT)
  1322.     {
  1323.         Log("netvis mode         [  Client, connected to %s ]\n", g_server_addr);
  1324.     }
  1325.     Log("netvis port         [ %7d ] [ %7d ]\n", g_port, DEFAULT_NETVIS_PORT);
  1326.     Log("netvis display rate [ %7d ] [ %7d ]\n", g_rate, DEFAULT_NETVIS_RATE);
  1327. #endif
  1328.  
  1329.     Log("\n\n");
  1330. }
  1331.  
  1332. // =====================================================================================
  1333. //  main
  1334. // =====================================================================================
  1335. int             main(const int argc, char** argv)
  1336. {
  1337.     char            portalfile[_MAX_PATH];
  1338.     char            source[_MAX_PATH];
  1339.     int             i;
  1340.     double          start, end;
  1341.     const char*     mapname_from_arg = NULL;
  1342.  
  1343. #ifdef ZHLT_NETVIS
  1344.     g_Program = "netvis";
  1345. #else
  1346.     g_Program = "hlvis";
  1347. #endif
  1348.  
  1349.     if (argc == 1)
  1350.     {
  1351.         Usage();
  1352.     }
  1353.  
  1354.     for (i = 1; i < argc; i++)
  1355.     {
  1356.         if (!strcasecmp(argv[i], "-threads"))
  1357.         {
  1358.             if (i < argc)
  1359.             {
  1360.                 g_numthreads = atoi(argv[++i]);
  1361.                 if (g_numthreads < 1)
  1362.                 {
  1363.                     Log("Expected value of at least 1 for '-threads'\n");
  1364.                     Usage();
  1365.                 }
  1366.             }
  1367.             else
  1368.             {
  1369.                 Usage();
  1370.             }
  1371.         }
  1372.  
  1373. #ifdef SYSTEM_WIN32
  1374.         else if (!strcasecmp(argv[i], "-estimate"))
  1375.         {
  1376.             g_estimate = true;
  1377.         }
  1378. #endif
  1379. #ifdef SYSTEM_POSIX
  1380.         else if (!strcasecmp(argv[i], "-noestimate"))
  1381.         {
  1382.             g_estimate = false;
  1383.         }
  1384. #endif
  1385. #ifdef ZHLT_NETVIS
  1386.         else if (!strcasecmp(argv[i], "-server"))
  1387.         {
  1388.             g_vismode = VIS_MODE_SERVER;
  1389.         }
  1390.         else if (!strcasecmp(argv[i], "-connect"))
  1391.         {
  1392.             if (i < argc)
  1393.             {
  1394.                 g_vismode = VIS_MODE_CLIENT;
  1395.                 g_server_addr = argv[++i];
  1396.             }
  1397.             else
  1398.             {
  1399.                 Usage();
  1400.             }
  1401.         }
  1402.         else if (!strcasecmp(argv[i], "-port"))
  1403.         {
  1404.             if (i < argc)
  1405.             {
  1406.                 g_port = atoi(argv[++i]);
  1407.             }
  1408.             else
  1409.             {
  1410.                 Usage();
  1411.             }
  1412.         }
  1413.         else if (!strcasecmp(argv[i], "-rate"))
  1414.         {
  1415.             if (i < argc)
  1416.             {
  1417.                 g_rate = atoi(argv[++i]);
  1418.             }
  1419.             else
  1420.             {
  1421.                 Usage();
  1422.             }
  1423.             if (g_rate < 5)
  1424.             {
  1425.                 Log("Minimum -rate is 5, setting to 5 seconds\n");
  1426.                 g_rate = 5;
  1427.             }
  1428.             if (g_rate > 900)
  1429.             {
  1430.                 Log("Maximum -rate is 900, setting to 900 seconds\n");
  1431.                 g_rate = 900;
  1432.             }
  1433.         }
  1434. #endif
  1435. #ifndef ZHLT_NETVIS
  1436.         else if (!strcasecmp(argv[i], "-fast"))
  1437.         {
  1438.             Log("g_fastvis = true\n");
  1439.             g_fastvis = true;
  1440.         }
  1441. #endif
  1442.         else if (!strcasecmp(argv[i], "-full"))
  1443.         {
  1444.             g_fullvis = true;
  1445.         }
  1446.         else if (!strcasecmp(argv[i], "-dev"))
  1447.         {
  1448.             if (i < argc)
  1449.             {
  1450.                 g_developer = (developer_level_t)atoi(argv[++i]);
  1451.             }
  1452.             else
  1453.             {
  1454.                 Usage();
  1455.             }
  1456.         }
  1457.         else if (!strcasecmp(argv[i], "-verbose"))
  1458.         {
  1459.             g_verbose = true;
  1460.         }
  1461.  
  1462.         else if (!strcasecmp(argv[i], "-noinfo"))
  1463.         {
  1464.             g_info = false;
  1465.         }
  1466.         else if (!strcasecmp(argv[i], "-chart"))
  1467.         {
  1468.             g_chart = true;
  1469.         }
  1470.         else if (!strcasecmp(argv[i], "-low"))
  1471.         {
  1472.             g_threadpriority = eThreadPriorityLow;
  1473.         }
  1474.         else if (!strcasecmp(argv[i], "-high"))
  1475.         {
  1476.             g_threadpriority = eThreadPriorityHigh;
  1477.         }
  1478.         else if (!strcasecmp(argv[i], "-nolog"))
  1479.         {
  1480.             g_log = false;
  1481.         }
  1482.         else if (!strcasecmp(argv[i], "-texdata"))
  1483.         {
  1484.             if (i < argc)
  1485.             {
  1486.                 int             x = atoi(argv[++i]) * 1024;
  1487.  
  1488.                 if (x > g_max_map_miptex)
  1489.                 {
  1490.                     g_max_map_miptex = x;
  1491.                 }
  1492.             }
  1493.             else
  1494.             {
  1495.                 Usage();
  1496.             }
  1497.         }
  1498.  
  1499. #ifdef ZHLT_PROGRESSFILE // AJM
  1500.         else if (!strcasecmp(argv[i], "-progressfile"))
  1501.         {
  1502.             if (i < argc)
  1503.             {
  1504.                 g_progressfile = argv[++i];
  1505.             }
  1506.             else
  1507.             {
  1508.                 Log("Error: -progressfile: expected path to progress file following parameter\n");
  1509.                 Usage();
  1510.             }
  1511.         }
  1512. #endif
  1513.         
  1514. #ifdef HLVIS_MAXDIST
  1515.         // AJM: MVD
  1516.         else if(!strcasecmp(argv[i], "-maxdistance"))
  1517.         {
  1518.             if(i < argc)
  1519.             {
  1520.                 g_maxdistance = abs(atoi(argv[++i]));
  1521.             }
  1522.             else
  1523.             {
  1524.                 Usage();
  1525.             }
  1526.         }
  1527. /*        else if(!strcasecmp(argv[i], "-postcompile"))
  1528.         {
  1529.             g_postcompile = true;
  1530.         }*/
  1531. #endif
  1532.  
  1533.         else if (argv[i][0] == '-')
  1534.         {
  1535.             Log("Unknown option \"%s\"", argv[i]);
  1536.             Usage();
  1537.         }
  1538.         else if (!mapname_from_arg)
  1539.         {
  1540.             mapname_from_arg = argv[i];
  1541.         }
  1542.         else
  1543.         {
  1544.             Log("Unknown option \"%s\"\n", argv[i]);
  1545.             Usage();
  1546.         }
  1547.     }
  1548.  
  1549. #ifdef ZHLT_NETVIS
  1550.     threads_InitCrit();
  1551.  
  1552.     if (g_vismode == VIS_MODE_CLIENT)
  1553.     {
  1554.         ConnectToServer(g_server_addr, g_port);
  1555.  
  1556.         while (!isConnectedToServer())
  1557.         {
  1558.             NetvisSleep(100);
  1559.         }
  1560.         Send_VIS_LOGIN();
  1561.         while (!g_clientid)
  1562.         {
  1563.             if (!isConnectedToServer())
  1564.             {
  1565.                 Error("Unexepected disconnect from server(4)\n");
  1566.             }
  1567.             NetvisSleep(100);
  1568.         }
  1569.  
  1570.         mapname_from_arg = "proxy";
  1571.     }
  1572.     else if (g_vismode == VIS_MODE_SERVER)
  1573.     {
  1574.         StartNetvisSocketServer(g_port);
  1575.  
  1576.         if (!mapname_from_arg)
  1577.         {
  1578.             Log("No mapfile specified\n");
  1579.             Usage();
  1580.         }
  1581.     }
  1582.     else
  1583.     {
  1584.         Log("Netvis must be run either as a server (-server)\n" "or as a client (-connect servername)\n\n");
  1585.         Usage();
  1586.     }
  1587.  
  1588. #else
  1589.  
  1590.     if (!mapname_from_arg)
  1591.     {
  1592.         Log("No mapfile specified\n");
  1593.         Usage();
  1594.     }
  1595. #endif
  1596.  
  1597. #ifdef ZHLT_NETVIS
  1598.     if (g_vismode == VIS_MODE_CLIENT)
  1599.     {
  1600.         g_log = false;
  1601.     }
  1602. #endif
  1603.  
  1604.     safe_strncpy(g_Mapname, mapname_from_arg, _MAX_PATH);
  1605.     FlipSlashes(g_Mapname);
  1606.     StripExtension(g_Mapname);
  1607.     OpenLog(g_clientid);
  1608.     atexit(CloseLog);
  1609.     ThreadSetDefault();
  1610.     ThreadSetPriority(g_threadpriority);
  1611.     LogStart(argc, argv);
  1612.  
  1613. #ifdef ZHLT_NETVIS
  1614.     if (g_vismode == VIS_MODE_CLIENT)
  1615.     {
  1616.         Log("ZHLT NETVIS Client #%d\n", g_clientid);
  1617.         g_log = false;
  1618.     }
  1619.     else
  1620.     {
  1621.         Log("ZHLT NETVIS Server\n");
  1622.     }
  1623. #endif
  1624.  
  1625.     CheckForErrorLog();
  1626.  
  1627.     dtexdata_init();
  1628.     atexit(dtexdata_free);
  1629.     // END INIT
  1630.  
  1631.     // BEGIN VIS
  1632.     start = I_FloatTime();
  1633.  
  1634.     safe_strncpy(source, g_Mapname, _MAX_PATH);
  1635.     safe_strncat(source, ".bsp", _MAX_PATH);
  1636.     safe_strncpy(portalfile, g_Mapname, _MAX_PATH);
  1637.     safe_strncat(portalfile, ".prt", _MAX_PATH);
  1638.  
  1639. #ifdef ZHLT_NETVIS
  1640.  
  1641.     if (g_vismode == VIS_MODE_SERVER)
  1642.     {
  1643.         LoadBSPFile(source);
  1644.         LoadPortalsByFilename(portalfile);
  1645.  
  1646.         char* bsp_image;
  1647.         char* prt_image;
  1648.  
  1649.         g_bsp_size = LoadFile(source, &bsp_image);
  1650.         g_prt_size = LoadFile(portalfile, &prt_image);
  1651.  
  1652.         g_bsp_compressed_size = (g_bsp_size * 1.01) + 12; // Magic numbers come from zlib documentation
  1653.         g_prt_compressed_size = (g_prt_size * 1.01) + 12; // Magic numbers come from zlib documentation
  1654.  
  1655.         char* bsp_compressed_image = (char*)malloc(g_bsp_compressed_size);
  1656.         char* prt_compressed_image = (char*)malloc(g_prt_compressed_size);
  1657.  
  1658.         int rval;
  1659.  
  1660.         rval = compress2((byte*)bsp_compressed_image, &g_bsp_compressed_size, (byte*)bsp_image, g_bsp_size, 5);
  1661.         if (rval != Z_OK)
  1662.         {
  1663.             Error("zlib Compression error with bsp image\n");
  1664.         }
  1665.  
  1666.         rval =  compress2((byte*)prt_compressed_image, &g_prt_compressed_size, (byte*)prt_image, g_prt_size, 7);
  1667.         if (rval != Z_OK)
  1668.         {
  1669.             Error("zlib Compression error with prt image\n");
  1670.         }
  1671.  
  1672.         free(bsp_image);
  1673.         free(prt_image);
  1674.  
  1675.         g_bsp_image = bsp_compressed_image;
  1676.         g_prt_image = prt_compressed_image;
  1677.     }
  1678.     else if (g_vismode == VIS_MODE_CLIENT)
  1679.     {
  1680.         Send_VIS_WANT_BSP_DATA();
  1681.         while (!g_bsp_downloaded)
  1682.         {
  1683.             if (!isConnectedToServer())
  1684.             {
  1685.                 Error("Unexepected disconnect from server(5)\n");
  1686.             }
  1687.             NetvisSleep(100);
  1688.         }
  1689.         Send_VIS_WANT_PRT_DATA();
  1690.         while (!g_prt_downloaded)
  1691.         {
  1692.             if (!isConnectedToServer())
  1693.             {
  1694.                 Error("Unexepected disconnect from server(6)\n");
  1695.             }
  1696.             NetvisSleep(100);
  1697.         }
  1698.         LoadPortals(g_prt_image);
  1699.         free(g_prt_image);
  1700.     }
  1701.  
  1702. #else // NOT ZHLT_NETVIS
  1703.  
  1704.     LoadBSPFile(source);
  1705.     ParseEntities();
  1706.     LoadPortalsByFilename(portalfile);
  1707.  
  1708. #   if ZHLT_ZONES
  1709.         g_Zones = MakeZones();
  1710.         AssignPortalsToZones();
  1711. #   endif
  1712.  
  1713. #endif
  1714.  
  1715.     Settings();
  1716.     g_uncompressed = (byte*)calloc(g_portalleafs, g_bitbytes);
  1717.  
  1718.     CalcVis();
  1719.  
  1720. #ifdef ZHLT_NETVIS
  1721.  
  1722.     if (g_vismode == VIS_MODE_SERVER)
  1723.     {
  1724.         g_visdatasize = vismap_p - g_dvisdata;
  1725.         Log("g_visdatasize:%i  compressed from %i\n", g_visdatasize, originalvismapsize);
  1726.  
  1727.         if (g_chart)
  1728.         {
  1729.             PrintBSPFileSizes();
  1730.         }
  1731.  
  1732.         WriteBSPFile(source);
  1733.  
  1734.         end = I_FloatTime();
  1735.         LogTimeElapsed(end - start);
  1736.  
  1737.         free(g_uncompressed);
  1738.         // END VIS
  1739.  
  1740. #ifndef SYSTEM_WIN32
  1741.         // Talk about cheese . . .
  1742.         StopNetvisSocketServer();
  1743. #endif
  1744.  
  1745.     }
  1746.     else if (g_vismode == VIS_MODE_CLIENT)
  1747.     {
  1748.  
  1749. #ifndef SYSTEM_WIN32
  1750.         // Dont ask  . . 
  1751.         DisconnectFromServer();
  1752. #endif
  1753.  
  1754.         end = I_FloatTime();
  1755.         LogTimeElapsed(end - start);
  1756.  
  1757.         free(g_uncompressed);
  1758.         // END VIS
  1759.     }
  1760.     threads_UninitCrit();
  1761.  
  1762. #else // NOT ZHLT_NETVIS
  1763.  
  1764.     g_visdatasize = vismap_p - g_dvisdata;
  1765.     Log("g_visdatasize:%i  compressed from %i\n", g_visdatasize, originalvismapsize);
  1766.  
  1767.     if (g_chart)
  1768.     {
  1769.         PrintBSPFileSizes();
  1770.     }
  1771.  
  1772.     WriteBSPFile(source);
  1773.  
  1774.     end = I_FloatTime();
  1775.     LogTimeElapsed(end - start);
  1776.  
  1777.     free(g_uncompressed);
  1778.     // END VIS
  1779.  
  1780. #endif // ZHLT_NETVIS
  1781.  
  1782.     return 0;
  1783. }
  1784.